#include <stdio.h>
#include <string.h>
#include "parse.h"
#include <assert.h>

void parse_cmd(char *line, struct cmd * cmd)  //分析简单命令,为方便编程，规定重定向符号前后必须有一个空格
{
    char *token,buf[100];
    int i=0,argc=0;
    strcpy(buf,line);
    token=strtok(buf," ");
    cmd->argv[0] = strdup(token);
    i++;
    while (token!=NULL) //分割命令
    {
        token = strtok(NULL, " ");
        if (token != NULL) {
            cmd->argv[i] = strdup(token);
            i++;
        }
    }
    //printf("%s",cmd->argv[i]);
    cmd->argv[i]=NULL;
    for(i=0;cmd->argv[i]!=NULL;i++)  //计算argc
    {
        if(strcmp(cmd->argv[i],"<")==0 || strcmp(cmd->argv[i],">")==0)
        i++; //跳过重定向和目标文件
        else 
        argc++;
    }

    cmd->argc=argc;
    cmd->input=NULL;
    cmd->output=NULL;

    for(i=0;cmd->argv[i]!=NULL;i++) //移除重定向符号和目标文件字符串
    {
        if(strcmp(cmd->argv[i],"<")==0)
        {
            if(cmd->argv[i+1]!=NULL)
            {
                cmd->input=cmd->argv[i+1];
                cmd->argv[i]=cmd->argv[i+1]=NULL;
            }
        }
        else if (strcmp(cmd->argv[i],">")==0)  
        {
             if(cmd->argv[i+1]!=NULL)
            {
                cmd->output=cmd->argv[i+1];
                cmd->argv[i]=cmd->argv[i+1]=NULL;
            }
        }
        
    }
    
    
}

int parse_pipe_cmd(char *line, struct cmd *cmdv) //分析一行管道命令，得到命令数量和各个命令
{
    char *part,buf[100],*save;
    int cmdc=0;
    strcpy(buf,line);
    buf[strcspn(buf,"\n")]='\0';
    part=strtok_r(buf,"|",&save);
    struct cmd *cmd;
    while(part!=NULL)
    {
        cmd=cmdv+cmdc;
        parse_cmd(part,cmd);  
        part=strtok_r(NULL,"|",&save);  //问题所在,通过修改parse_cmd消除了错误
        cmdc++;
    }
    return cmdc;
}

// echo abc
void test_parse_cmd_1()
{
    struct cmd cmd;
    char line[] = "echo abc xyz";
    parse_cmd(line, &cmd);

    assert(cmd.argc == 3);
    assert(strcmp(cmd.argv[0], "echo") == 0);
    assert(strcmp(cmd.argv[1], "abc") == 0);
    assert(strcmp(cmd.argv[2], "xyz") == 0);
    assert(cmd.argv[3] == NULL);
    printf("test_parse_cmd_1\tpass\n");
}

// echo abc > log
void test_parse_cmd_2()
{
    struct cmd cmd;
    char line[] = "echo abc > log";
    parse_cmd(line, &cmd);

    assert(cmd.argc == 2);
    assert(strcmp(cmd.argv[0], "echo") == 0);
    assert(strcmp(cmd.argv[1], "abc") == 0);
    assert(cmd.argv[2] == NULL);
    assert(strcmp(cmd.output,"log")==0);
    printf("test_parse_cmd_2\tpass\n");
}

// cat /etc/passwd | wc -l
void test_parse_pipe_cmd_1()
{
    struct cmd cmdv[2];
    char line[]="cat /etc/passwd | wc -l";
    parse_pipe_cmd(line,cmdv);
    assert(cmdv[0].argc==2);
    assert(strcmp(cmdv[0].argv[0],"cat")==0);
    assert(strcmp(cmdv[0].argv[1],"/etc/passwd")==0);
    assert(cmdv[0].argv[2]==NULL);
    assert(cmdv[1].argc==2);
    assert(strcmp(cmdv[1].argv[0],"wc")==0);
    assert(strcmp(cmdv[1].argv[1],"-l")==0);
    assert(cmdv[1].argv[2]==NULL);
    printf("test_parse_pipe_cmd_1\tpass\n");
}

// cat < input | sort | cat > output
void test_parse_pipe_cmd_2()
{
    struct cmd cmdv[3];
    char line[]={"cat < input | sort | cat > output"};
    parse_pipe_cmd(line,cmdv);
    assert(cmdv[0].argc==1);
    assert(strcmp(cmdv[0].argv[0],"cat")==0);
    assert(strcmp(cmdv[0].input,"input")==0);
    assert(cmdv[0].argv[1]==NULL);
    assert(cmdv[1].argc==1);
    assert(strcmp(cmdv[1].argv[0],"sort")==0);
    assert(cmdv[1].argv[1]==NULL);
    assert(cmdv[2].argc==1);
    assert(strcmp(cmdv[2].argv[0],"cat")==0);
    assert(cmdv[2].argv[1]==NULL);
    assert(strcmp(cmdv[2].output,"output")==0);
    printf("test_parse_pipe_cmd_1\tpass\n");

}
